.global setjmp
.global longjmp
/*
typedef struct my_jmp_buffer
{
	unsigned long ebx;
	unsigned long eax;
	unsigned long ecx;
	unsigned long edx;
	unsigned long ebp;
	unsigned long esp;
	unsigned long edi;
	unsigned long esi;
	unsigned long ret_address;
	unsigned long eflags;
} my_jmp_buffer_t;
*/

/* offset const */
OFFSET_EBX = 0
OFFSET_EAX = OFFSET_EBX + 4 
OFFSET_ECX = OFFSET_EAX + 4
OFFSET_EDX = OFFSET_ECX + 4
OFFSET_EBP = OFFSET_EDX + 4
OFFSET_ESP = OFFSET_EBP + 4 
OFFSET_EDI = OFFSET_ESP + 4
OFFSET_ESI = OFFSET_EDI + 4
OFFSET_RET = OFFSET_ESI + 4
OFFSET_EFLAGS = OFFSET_RET + 4


setjmp:
	push %ebp
	mov  %esp, %ebp
	movl  8(%ebp), %eax
	movl %ebx, OFFSET_EBX(%eax)
	movl %ecx, OFFSET_ECX(%eax)
	movl %edx, OFFSET_EDX(%eax)
	pushl (%ebp)
	popl  OFFSET_EBP(%eax)
	movl %esp, OFFSET_ESP(%eax)
	addl $4, OFFSET_ESP(%eax)
	movl %edi, OFFSET_EDI(%eax)
	movl %esi, OFFSET_ESI(%eax)
	pushfl
	popl OFFSET_EFLAGS(%eax)

	// use ebx as base address index
	pushl %ebx
	movl 4(%ebp), %ebx		// save ret address
	movl %ebx, OFFSET_RET(%eax)
	popl %ebx

	movl $0, %eax
	leave
	ret

// void restore_registers(my_jmp_buffer_t * buf, void *src, void *dst, int size, int val);
BUF_INDEX = 8
RETVAL_INDEX = BUF_INDEX + 4

longjmp:
	pushl %ebp
	movl  %esp, %ebp
	// get the pointer of parameter
	movl   BUF_INDEX(%ebp), %eax

	// save return value to safe place
	movl RETVAL_INDEX(%ebp), %esi
	movl %esi, OFFSET_EAX(%eax)
	
	// restore registers
	movl OFFSET_ESI(%eax), %esi
	movl OFFSET_EDI(%eax), %edi
	movl OFFSET_EDX(%eax), %edx
	movl OFFSET_ECX(%eax), %ecx
	movl OFFSET_EBX(%eax), %ebx
	movl OFFSET_EBP(%eax), %ebp
	movl OFFSET_ESP(%eax), %esp

	// restore eflags
	pushl OFFSET_EFLAGS(%eax)
	popfl

	// save the return address
	addl $4, %esp
	pushl OFFSET_RET(%eax)

	movl OFFSET_EAX(%eax), %eax
	andl %eax, %eax
	jnz 1f
	incl %eax
1:
	ret
